/*
 * hkasm - A universal algebraic user defined assembler (for microcontrollers etc....)
 * Copyright (C) 2009  Henri Koskela <henri.koskela@iki.fi>
 *
 * This program is free software; you can redistribute it and/or modify
 * it under the terms of the GNU General Public License as published by
 * the Free Software Foundation; either version 2 of the License, or
 * (at your option) any later version.
 *
 * This program is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 * GNU General Public License for more details.
 *
 * You should have received a copy of the GNU General Public License
 * along with this program; if not, write to the Free Software
 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
 */

using System;
using System.Text.RegularExpressions;
using System.Collections;
using System.Collections.Generic;


/**
 * Misc. Binary-hex-string-char operations
 */
static class BinOperations{
		
	static public bool isAlphanumeric(char c){
		Regex regexAlphaNum=new Regex("[^a-zA-Z0-9]");
		return !regexAlphaNum.IsMatch(c.ToString());
	}
	static public bool isHexcharacter(char c){
		Regex regexHexNum=new Regex("[^a-fA-F0-9]");
		return !regexHexNum.IsMatch(c.ToString());
	}
		
	static public string byte2hex(byte b){
		string result=Convert.ToString(b,16);
		if (b<16) result="0"+result;
		return result;
	}
		
	/**
	 * Converts hex and binary numbers with prefixes 0x and 0b
	 */
	static public long string2number(string s){
		try{
			if (s.Contains("0x"))
				return (long)Convert.ToInt64(s.Replace("0x","").Trim(),16);
			if (s.Contains("0b"))
				return (long)Convert.ToInt64(s.Replace("0b","").Trim(),2);
		}catch{
			throw new Exception("Converting "+s+" to value failed");
		}
		try{
			return (long)Convert.ToInt64(s.Trim(),10);
			
		}catch{
			throw new Exception("Can't convert "+s+" to int64");
		}
		return 0;
	}

	/**
	* Converts to number to binstring (notify 
	*/
	static public string number2binString(long number){
		if (number<0)
			return Convert.ToString(~number+1,2);
		return Convert.ToString(number,2);
	}
		
	static public string number2binString(long number,int bits){
		//TODO NEGATIIVISET LUVUT
		string s=number2binString(number);
		if (s.Length>bits){
			throw new Exception("Value "+number+" won't fit in "+bits+" bits!!!");
		}
		if (number>0){
			while(s.Length<bits) s="0"+s;
		}else{
			while(s.Length<bits) s="1"+s; //2-complement!!!!
		}
		return s;
	}
		
	/**
	 * Seek 0x hex and 0b binary numbers from string and convert them to 10-base
	 */
	static public string seekAndConvertBase10(string line){
		while(line.Contains("0x")||(line.Contains("0b"))){
			int location;
			int count;
				
			if (line.Contains("0x")){
				location=line.IndexOf("0x");
				for(count=2;(count+location)<line.Length;count++){
					char c=(line.ToUpper())[location+count];
					if (!BinOperations.isHexcharacter(c)) break;
				}
				line=line.Substring(0,location)+(string2number(line.Substring(location,count))).ToString()+line.Substring(location+count);
			}
				
			if (line.Contains("0b")){
				location=line.IndexOf("0b");
				for(count=2;(count+location)<line.Length;count++){
					char c=line[location+count];
					if ((c!='0')&&(c!='1')) break;
				}
				line=line.Substring(0,location)+(string2number(line.Substring(location,count))).ToString()+line.Substring(location+count);
			}
		}
		return line;
	}
	
	public static byte[] toByteData(ArrayList a){
		ArrayList tmp=new ArrayList();
		foreach(string s in a){
			string src=s;
			while(src.Length>0){
				tmp.Add(Convert.ToInt64(src.Substring(0,8)));
				src=src.Substring(8);
			}
		}
		byte[] result=new byte[tmp.Count];
		for(int i=0;i<result.Length;i++)
			result[i]=Convert.ToByte(tmp[i].ToString(),2);
		return result;
	}
		
	public static byte[] chanceByteEndian(byte[] input){
		byte[] result=new byte[input.Length];
		for(int i=0;i<result.Length;i+=2){
			result[i]=input[i+1];
			result[i+1]=input[i];
		}
		return result;
	}
}
